package com.xs.tool;


import lombok.experimental.UtilityClass;

import javax.validation.constraints.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.util.*;

@UtilityClass
public class ValidateUtil {

    private boolean isSupportedConstraint(String type) {
        return switch (type) {
            case "javax.validation.constraints.NotNull",
                 "javax.validation.constraints.NotBlank",
                 "javax.validation.constraints.NotEmpty",
                 "javax.validation.constraints.Size",
                 "javax.validation.constraints.Min",
                 "javax.validation.constraints.Max",
                 "javax.validation.constraints.Positive",
                 "javax.validation.constraints.Negative",
                 "javax.validation.constraints.Pattern",
                 "javax.validation.constraints.Email" -> true;
            default -> false;
        };
    }

    public void validateSingleParam(int index, Object value, Annotation annotation) {
        try {

            boolean supportedConstraint = isSupportedConstraint(annotation.annotationType().getName());
            if (!supportedConstraint) {
                return;
            }
            switch (annotation) {
                case NotNull a -> {
                    if (value == null) {
                        String msg;
                        if (a.message().equals("{javax.validation.constraints.NotNull.buffInfo}")) {
                            msg = "参数 index:" + index + " 不能为 null";
                        } else {
                            msg = "参数 index:" + index + a.message() + " 不能为 null";
                        }
                        throw new IllegalArgumentException(msg);
                    }
                }
                case NotBlank a -> validateNotBlank((String) value, a.message());
                case NotEmpty a -> validateNotEmpty(value, a.message());
                case Size a -> validateSize(value, a.min(), a.max(), a.message());
                case Min a -> validateMin((Number) value, a.value(), a.message());
                case Max a -> validateMax((Number) value, a.value(), a.message());
                case Positive a -> validatePositive((Number) value, a.message());
                case Negative a -> validateNegative((Number) value, a.message());
                case Email a -> validateEmail((String) value, a.message());
                default -> {
                    // 不处理未知注解
                }
            }
        } catch (Exception e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    private void validateNotBlank(String value, String message) {
        if (value == null || value.trim().isEmpty())
            throw new IllegalArgumentException(message);
    }

    private void validateNotEmpty(Object value, String message) {
        if (value instanceof String s && s.isEmpty()) {
            throw new IllegalArgumentException(message);
        } else if (value instanceof Collection<?> c && c.isEmpty()) {
            throw new IllegalArgumentException(message);
        } else if (value.getClass().isArray() && Array.getLength(value) == 0) {
            throw new IllegalArgumentException(message);
        }
    }

    private void validateSize(Object value, int min, int max, String message) {
        int length = -1;
        if (value instanceof String s) {
            length = s.length();
        } else if (value instanceof Collection<?> c) {
            length = c.size();
        } else if (value.getClass().isArray()) {
            length = Array.getLength(value);
        }

        if (length >= 0 && (length < min || length > max))
            throw new IllegalArgumentException(message);
    }

    private void validateMin(Number value, long min, String message) {
        if (value != null && value.doubleValue() < min)
            throw new IllegalArgumentException(message);
    }

    private void validateMax(Number value, long max, String message) {
        if (value != null && value.doubleValue() > max)
            throw new IllegalArgumentException(message);
    }

    private void validatePositive(Number value, String message) {
        if (value != null && value.doubleValue() <= 0)
            throw new IllegalArgumentException(message);
    }

    private void validateNegative(Number value, String message) {
        if (value != null && value.doubleValue() >= 0)
            throw new IllegalArgumentException(message);
    }

    private void validatePattern(String value, String regex, String message) {
        if (value != null && !value.matches(regex))
            throw new IllegalArgumentException(message);
    }

    private void validateEmail(String value, String message) {
        if (value != null) {
            String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
            if (!value.matches(emailRegex))
                throw new IllegalArgumentException(message);
        }
    }
}